import { ICartridge, IROMInfo, Mirror } from "../api/cartridge";
import { IMapper } from "../api/mapper";
import { Mapper0 } from "../mapper/mapper0";

enum HEADER {
    PRG = 4,
    CHR = 5,
    FLAG1 = 6,
    FLAG2 = 7
}


class Cartridge implements ICartridge {
    public readonly mapper: IMapper;
    public readonly info: IROMInfo = {} as any;

    constructor(data: Uint8Array, sram: Uint8Array) {
        Cartridge.checkConstant(data)
        this.parseROMInfo(data)

        const prgOffset = this.info.isTrained ? 16 + 512 : 16;
        const prg = data.slice(prgOffset, prgOffset + this.info.prg * 16 * 1024)

        const chrOffset = prgOffset + prg.length;
        const chr = data.slice(chrOffset, chrOffset + this.info.chr * 8 * 1024);

        switch (this.info.mapper) {
            case 0:
                this.mapper = new Mapper0(sram, prg, chr)
                break;
            default:
                throw new Error(`不支持的Mapper：${this.info.mapper}`)
        }
    }

    private parseROMInfo(data: Uint8Array) {
        // 读取PRG和Chr的数目
        this.info.prg = data[HEADER.PRG];
        this.info.chr = data[HEADER.CHR]

        const mapperL = data[HEADER.FLAG1] >> 4;
        const mapperH = data[HEADER.FLAG2] >> 4;
        this.info.mapper = mapperH << 4 | mapperL;
        this.info.mirror = data[HEADER.FLAG1] & 0x08
            ? Mirror.FOUR_SCREEN
            : data[HEADER.FLAG1] & 0x01
                ? Mirror.VERTICAL
                : Mirror.HORIZONTAL;
        this.info.isTrained = !!(data[HEADER.FLAG1] & 0x04)

    }
    static checkConstant(data: Uint8Array) {
        let str = 'NES\u001a'
        for (let i = 0; i < str.length; i++) {
            if (data[i] !== str.charCodeAt(i)) {
                throw new Error("无效nes文件");
            }
        }
        //            data[7]
        // 0000 1100  
        // 0000 0100 
        if ((data[7] & 0x0C) === 0x08) {
            throw new Error('NES2.0 is not currently supported');
        }
    }
}

export {
    Cartridge
}